package com.aphrodite.ui.widgets;

import java.util.Timer;
import java.util.TimerTask;

import javax.microedition.lcdui.Graphics;

/**
 * Animated loading bar
 * 
 * @author kentelt
 * 
 */
public final class LoadingBar extends Widget {

	private final class Ani extends TimerTask {
		public void run() {
			while (isLoading) {
				currNumber++;
				if (currNumber > blockCanAccom) {
					currNumber = 1;
				}
				reDrawWidget();
				try {
					Thread.sleep(delay);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/*
	 * Number of blocks that can be acccomdated
	 */
	private int blockCanAccom;
	/*
	 * Space between blocks
	 */
	private int blockPad = 5;
	/*
	 * width of each block
	 */
	private int blockWidth = 20;
	private int currNumber;
	private int delay = 500;
	private volatile boolean isLoading;

	private Timer timer;

	public LoadingBar(Theme theme) {
		this(theme, 90, 5);
	}

	/**
	 * Create a loading bar instance
	 * 
	 * @param width
	 *            of the loading bar
	 * @param height
	 *            of the loading bar
	 */
	public LoadingBar(Theme theme, int width, int height) {
		super(theme, width, height);
		updateModel();
		startLoading();
	}

	public void cleanUp() {

	}

	public void render(Graphics g) {
		if (!isVisible)
			return;
		capture(g, width, height, true);
		g.setColor(theme.fgColor);
		for (int i = 0; i < currNumber; i++) {
			g.fillRect((i * blockPad) + (i * blockWidth), 0, blockWidth, height);
		}
		release(g, width, height, true);

	}

	/**
	 * Space between each block
	 * 
	 * @param blkPad
	 */
	public void setBlockPad(int blkPad) {
		this.blockPad = blkPad;
		updateModel();
		reDrawWidget();
		stateChanged(this);
	}

	/**
	 * Width of each block
	 * 
	 * @param blkWidth
	 * @throws IllegalArgumentException
	 *             if <code>blkWidth>width</code>
	 */
	public void setBlockWidth(int blkWidth) {
		if (blkWidth > width) {
			throw new IllegalArgumentException();
		}
		this.blockWidth = blkWidth;
		updateModel();
		reDrawWidget();
		stateChanged(this);
	}

	/**
	 * Set the delay in drawing individual blocks
	 * 
	 * @param millisec
	 *            Default is 500ms.
	 */
	public void setDelayInterval(int millisec) {
		this.delay = millisec;
	}

	public void setVisible(boolean isVisible) {
		super.setVisible(isVisible);
		/* stop bg thread when not visible */
		if (!isVisible) {
			stopLoading();
		} else {
			startLoading();
		}
	}

	/**
	 * Start loading animation
	 */
	public void startLoading() {
		if (!isLoading) {
			isLoading = true;
			if (timer != null) {
				timer.cancel();
				timer = null;
			}
			timer = new Timer();
			timer.schedule(new Ani(), 0);
		}
	}

	/**
	 * Stop loading animation
	 */
	public void stopLoading() {
		if (isLoading) {
			isLoading = false;
			timer.cancel();
			timer = null;
			currNumber = 0;
		}
	}

	protected void updateModel() {
		int tmpW = 0;
		blockCanAccom = 0;
		while (tmpW < width) {
			blockCanAccom++;
			tmpW += blockWidth + blockPad;
		}
	}

}
